STM32L431移植LiteOS 手把手教程
很荣幸很大家分享LiteOS的移植,这里我们移植的对象是ST的STM32L431,用的开发板是EVB_M1开发板,不罗嗦,直接上教程!
一、环境准备
1. 硬件环境准备
1.1 EVB_M1开发板
“EVB_M1”NB-IoT开发板,是“物联网俱乐部”正式销售的第一款带低功耗STML4单片机的开发板。开发板具有丰富的资源外设,以及灵活的传感器扩展板搭配方案,让您在NB-IoT产品的开发道路上更加便捷。EVB_M1自从上市以来广受好评,成为广大开发者学习NB-IoT、LiteOSC、OceanConnect的利器。
1.2 STlink仿真器
下载器,用于调试下载STM32芯片程序。
2. 软件环境
2.1 MDK ARM 集成开发软件
本移植指南使用的微控制器集成开发环境为MDK5.25,
下载地址:https://www.keil.com/demo/eval/arm.htm
芯片器件支持包:MDK安装完成后,要支持具体芯片的开发,还需要安装相应芯片器件支持包,比如EVB_M1开发板的主芯片是STM32L431RCT6,需要安装Keil.STM32L4xx_DFP.2.0.0.pack,
下载地址:http://www.keil.com/dd2/Pack/#/eula-container
下载完成后直接双击即可安装。
2.2 开发板对应裸机工程
LiteOS移植需要提供开发板对应的裸机工程
本文裸机工程将使用STM32官方的STM32CubeMX软件生成,
该软件的下载地址为:
使用STM32CubeMX还需要安装JDK环境,开发者可以按照网上方法安装,此处不再赘述。
3. LiteOS源码准备
Huawei LiteOS开源代码托管在GitHub的LiteOS工程目录下,
下载地址:https://github.com/LiteOS/LiteOS
进去后先将分支切换成develop,然后点击Clone or download下载LiteOS源码。
LiteOS官方提供的内核源码目录介绍:
由于这里主要介绍的是LiteOS内核移植,我们涉及到的只有3个目录下的内容:arch、components/cmsis和kernel。下面介绍的移植过程也只涉及到这三个目录下的源码。
二、内核移植
1. 使用STM32CubeMX新建STM32L431RCT6裸机工程
1.1 启动STM32CubeMX后先新建工程
1.2 选择单板
如上图中标识序号
- 1:可以选择通过MCU还是Board来创建工程
- 2:设置单板筛选条件
- 3:选择对应的单板芯片双击创建工程
1.3配置引脚信息
如上图中标识序号
- 1:选择Pinout标签页
- 3:这里作为示例,只选择配置串口1 的引脚,并选择配置成异步方式。根据使用情况,可配置其他不同组件的引脚
1.4 配置时钟频率信息
1.5 选择功能模块的参数配置
1.6配置生成的工程参数和路径
1.7代码生成配置
注意: 需勾选对相应选项如图示,对应组件的代码(如串口)分别写在单独的.c和.h文件中,否则将全生成在main.c文件中。
1.8 生成裸机工程
点击图示按钮即可生成STM32L431开发板的裸机工程。
1.9查看keil工程
点击OK,生成工程效果如下:
至此STM32L431 EVB_M1 裸机工程生成成功,该工程可直接编译并烧写在板子上运行。
2.加入内核源码
加入内核源码之前,请将之前生成的裸机工程放入targets目录下,保持和LiteOS目录一致。将arc和components\cmsis两个目录下的源码也加入工程,后续操作涉及到的目录如下,其他不涉及的暂不列举
点击以上按钮,添加OS代码:
LiteOS
├─ arch
├─ components\cmsis
├─ kernel
├─ targets
└─ Standard_STM32L431_EVB_M1 // “使用CubeMX新建STM32裸机工程”步骤构建的裸机工程
···
2.1 添加cmsis os代码
2.2 添加内核代码
按照以上标注的源码路径添加LiteOS内核代码,需要注意的是,LiteOS提供了3套动态内存分配算法,位于 LiteOS\kernel\base\mem 目录下,分别是bestfit、bestfit_little、tlsf,这三套动态内存算法只需要添加其中一套就行了,对于资源有限的芯片,建议选bestfit_little,上面示例也是添加了这一套动态内存算法;另外 LiteOS\kernel\base\mem\membox 目录下是LiteOS提供的静态内存算法,与动态内存算法不冲突,需要添加; LiteOS\kernel\base\mem\common 目录的内容需要全部添加。
2.3 添加arch(平台相关)代码
los_dispatch_keil.S 文件为LiteOS的调度汇编,每个芯片IP核都不一样,比如本文使用的STM32L431 是ARM Cortex M4,编译IDE是keil,所以选择 LiteOS\arch\arm\arm-m\cortex-m4\keil ,如果你的开发板是M0核,GCC编译器,则选择 LiteOS\arch\arm\arm-m\cortex-m0\gcc 的 los_dispatch_gcc.S ;而 LiteOS\arch\arm\arm-m\src 则是ARM cortex M核公用的tick,中断,硬件堆栈实现文件。
2.4 添加内核以及平台相关代码的头文件目录
第一步:
第二步:
第三步:
OS_CONFIG 文件夹下的三个头文件为LiteOS配置模板,需要开发者自行拷贝到自己的目标板源码目录下,对于ARM Cortex M系列,只需要修改 target_config.h 中的参数就可以完成操作系统的配置。
至此内核源码加入完成。
3. 创建LiteOS任务
开发者在Appplication/User目录下找到main.c函数,在main.c里面先增加LiteOS头文件,对于创建任务一般只需要增加以下几个头文件:
/* Includes LiteOS------------------------------------------------------------------*/ #include "los_base.h" #include "los_sys.h" #include "los_typedef.h" #include "los_task.ph"
然后在main函数中增加任务创建函数,比如这里我们创建了两个任务task1和task2,示例代码如下:
void task1(void) { int count = 1; while (1) { printf("This is task1,count is %d\r\n",count++); LOS_TaskDelay(1000); } } UINT32 creat_task1() { UINT32 uwRet = LOS_OK; TSK_INIT_PARAM_S task_init_param; task_init_param.usTaskPrio = 0; task_init_param.pcName = "task1"; task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)task1; task_init_param.uwStackSize = 0x200; uwRet = LOS_TaskCreate(&g_TskHandle, &task_init_param); if(LOS_OK != uwRet) { return uwRet; } return uwRet; } void task2(void) { int count = 1; while (1) { printf("This is task2,count is %d\r\n",count++); LOS_TaskDelay(2000); } } UINT32 creat_task2() { UINT32 uwRet = LOS_OK; TSK_INIT_PARAM_S task_init_param; task_init_param.usTaskPrio = 1; task_init_param.pcName = "task2"; task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)task2; task_init_param.uwStackSize = 0x200; uwRet = LOS_TaskCreate(&g_TskHandle, &task_init_param); if(LOS_OK != uwRet) { return uwRet; } return uwRet; }
最后,在main函数中初始化LiteOS内核,创建task1 和task2,然后调用LOS_ Start函数就可以启动LiteOS了。
uwRet = LOS_KernelInit(); if (uwRet != LOS_OK) { return LOS_NOK; } uwRet = creat_task1(); if (uwRet != LOS_OK) { return LOS_NOK; } uwRet = creat_task2(); if (uwRet != LOS_OK) { return LOS_NOK; } LOS_Start();
4. 配置LiteOS
LiteOS内核的板级配置均在target_config.h中完成,target_config.h配置文件模板请参考其他工程的OS_CONFIG文件夹,2.2章节第4部分已经介绍,展开介绍主要配置项:
LOS_Start();#define OS_SYS_CLOCK (SystemCoreClock) //配置CPU主频,需要用户更改 #define LOSCFG_PLATFORM_HWI NO //配置OS是否接管中断 #define LOSCFG_PLATFORM_HWI_LIMIT 32 //配置外部中断数目 #define LOSCFG_BASE_CORE_TSK_LIMIT3//配置支持的最大任务数量 #define LOSCFG_BASE_IPC_SEM_LIMIT 2//配置支持的最大信号量数量 #define LOSCFG_BASE_IPC_MUX_LIMIT 2 //配置支持的最大互斥锁数量 #define LOSCFG_BASE_IPC_QUEUE_LIMIT 2 //配置支持的最大队列数量 #define LOSCFG_BASE_CORE_SWTMR_LIMIT 2 //配置支持的最大软件定时器数量 #define BOARD_SRAM_START_ADDR 0x20000000 //配置目标芯片RAM起始地址 #define BOARD_SRAM_SIZE_KB 8 //配置目标芯片RAM大小,单位KB #define CMSIS_OS_VER 2 //配置CMSIS OS版本,支持V1和V2
这里
•用户根据自身硬件情况修改上述配置,特别是CPU主频和RAM尺寸要根据情况修改;
•本教程要求OS不接管中断,接管中断的方式需要自行修改sct文件,所以推荐初级用户先不要使能接管中断的方式;
•最大任务数、信号量数、互斥锁数、队列数、软件定时器数建议用户根据实际需要配置合理的数量,数量太多会占用额外的RAM资源;
5. 编译下载LiteOS
按照上图步骤编译下载LiteOS,就可以在开发板中运行LiteOS了,串口打印效果如下图所示,显示两个任务交替运行:
补充:
------------------------------------------------------------------------------------------------
如何编译出现Systick 和pendsv函数重复定义,只需要在LiteOS\targets\Standard_STM32L431_EVB_M1\Src\stm32l4xx_it.c文件的两个函数前面加上__weak 关键字进行修饰即可,因为LiteOS内部也对这两个函数进行了定义,避免重复可以如此处理,如下图所示:
- 点赞
- 收藏
- 关注作者
评论(0)